/*
 * @Author: xiehangyun 
 * @Date: 2025-02-27 09:57:40 
 * @Last Modified by: xiehangyun
 * @Last Modified time: 2025-02-27 19:08:43
 */

import FabricCanvas from "@/myFabric/FabricCanvas";
import FabricImage from "@/myFabric/FabricImage";
import utils from "@/utils/utils";
import { fabric } from "fabric";
import { cloneDeep, debounce, isString } from "lodash";
import { EventDispatcher } from "three";
import closeSVG from "./img/close.svg";
import { autorun } from "mobx";
import addBgModalStore from "./addBgModalStore";

// 关闭控制器控制器
const removeContorls = new class RemoveContorls extends fabric.Control {

  icon = (() => {
    const icon = new fabric.Image("");
    icon.setSrc(closeSVG, () => {
      icon.set({
        scaleX: 0.1,
        scaleY: 0.1,
      });
    }, { crossOrigin: 'anonymous' });
    return icon;
  })();

  x = -0.5;
  y = -0.5;

  offsetY = 0;

  //@ts-ignore
  // actionHandler = () => { };
  //@ts-ignore
  // cursorStyleHandler = fabric.controlsUtils.rotationStyleHandler;
  withConnection = true;
  actionName = "close";
  cursorStyle = 'pointer';

  mouseUpHandler = (eventData: any, transform: any) => {
    const target = transform.target; // 获取被点击的对象
    const canvas = target.canvas; // 获取画布对象
    canvas.remove(target); // 从画布中移除对象
    addBgModalRender.recordHistory();
    return false;
  }

  render(ctx: CanvasRenderingContext2D, left: number, top: number, styleOverride: any, fabricObject: fabric.Object) {
    this.icon.set({
      originX: "center",
      originY: "center",
      left,
      top,
      angle: fabricObject.angle
    });
    this.icon.render(ctx);
  }
};



// 添加背景信息
class AddBgModalRender extends EventDispatcher {
  constructor() {
    super();
    window.addBgModalRender = this;
  }

  //fabric.js画布
  fabricCanvas = (() => {
    const fabricCanvas = new FabricCanvas(null);
    //渲染之前
    fabricCanvas.on('before:render', () => {
      const ctx = this.fabricCanvas.getContext();
      if (isString(this.fabricCanvas.backgroundColor) && fabric.Color.sourceFromHex(this.fabricCanvas.backgroundColor)) {
        ctx.fillStyle = this.fabricCanvas.backgroundColor as string;
        ctx.fillRect(0, 0, 1024, 1024);
      }
    });
    //渲染完成后

    fabricCanvas.on('after:render', () => {
      if (this.perCanvasCtx && this.fabricCanvas.getHeight() > 0 && this.fabricCanvas.getWidth() > 0) {
        this.perCanvasCtx.clearRect(0, 0, 1024, 1024);
        if (isString(this.fabricCanvas.backgroundColor) && fabric.Color.sourceFromHex(this.fabricCanvas.backgroundColor)) {
          this.perCanvasCtx.fillStyle = this.fabricCanvas.backgroundColor as string;
          this.perCanvasCtx.fillRect(0, 0, 1024, 1024);
        }
        const objects = this.fabricCanvas.getObjects();
        for (let obj of objects) {
          if (obj instanceof FabricImage) {
            obj.scaleX! *= 5.12;
            obj.scaleY! *= 5.12;
            obj.left! *= 5.12;
            obj.top! *= 5.12;
            obj.render(this.perCanvasCtx);
            obj.scaleX! /= 5.12;
            obj.scaleY! /= 5.12;
            obj.left! /= 5.12;
            obj.top! /= 5.12;
          }
        }
        // this.perCanvasCtx.drawImage(this.fabricCanvas.getElement(), 0, 0);
        this.perCanvasCtx.drawImage(this.currentBgImg, 0, 0, 1024, 1024);
      }

      // 保存当前存储的背景的fabric.js 数据
      addBgModalStore.changeMockupData(addBgModalStore.currentIndex, this.fabricCanvas.toJSON());

    });

    // 监听画布事件并记录历史
    fabricCanvas.on('object:added', (e) => {
      this.recordHistory();
    });

    fabricCanvas.on('object:modified', (e) => {
      this.recordHistory();
    });

    fabricCanvas.on('object:removed', (e) => {
      this.recordHistory();
    });

    return fabricCanvas;
  })();

  //预览canvas
  perCanvas?: HTMLCanvasElement;
  perCanvasCtx?: CanvasRenderingContext2D;
  //设置1024*1024的预览canvas
  setPerCanvas(perCanvas: HTMLCanvasElement | null) {
    if (perCanvas) {
      this.perCanvas = perCanvas;
      this.perCanvasCtx = this.perCanvas.getContext('2d') as CanvasRenderingContext2D;
    }
  }

  //当前选中的上身效果图的img
  currentBgImg = (() => {
    const currentBgImg = new Image();
    currentBgImg.crossOrigin = 'anonymous';
    return currentBgImg;
  })();
  
  //设置上面这个图片的src
  setCurrentBgImg(src: string) {
    this.currentBgImg.src = src;
    this.currentBgImg.onload = () => {
      this.fabricCanvas.requestRenderAll();
    }
  }

  // 设置容器
  async setContainer(div: HTMLDivElement | null) {
    if (div) {
      await new Promise(resolve => requestAnimationFrame(resolve));
      div.style.overflow = 'hidden';
      div.innerHTML = '';
      div.append(this.fabricCanvas.getElement());
      div.append(this.fabricCanvas.getSelectionElement());
      //计算div的宽高
      const width = div.clientWidth;
      const height = div.clientHeight;
      //设置画布宽高
      this.fabricCanvas.includeDefaultValues = false;
      this.fabricCanvas.setWidth(width);
      this.fabricCanvas.setHeight(height);
      this.fabricCanvas.renderAll();
    }
  }

  //重置数据
  async loadData(data: any) {
    await new Promise<void>(resolve => {
      this.fabricCanvas.loadFromJSON(data, () => {
        const objects = this.fabricCanvas.getObjects();
        for (let obj of objects) {
          if (obj instanceof FabricImage) {
            obj.set({
              containsPoint(point: any, lines: any, absolute: any, calculate: any) {
                // 拾取计算
                return true;
              },
              controls: {
                ...obj.controls,
                tl: removeContorls
              }
            });
          }
        }
        this.fabricCanvas.renderAll();
        resolve();
      });
    });
    if (this.historyEnable) {
      this.undoStack = [];
    }
    this.recordHistory();
  }

  //设置背景颜色
  setBgColor(color: string) {
    this.fabricCanvas.setBackgroundColor(color, () => {
      this.fabricCanvas.requestRenderAll();
    });
  }

  //清空画布元素
  clear() {
    this.fabricCanvas._objects = [];
    this.fabricCanvas.discardActiveObject();
    this.fabricCanvas.requestRenderAll();
  }

  //设置背景图片
  async setBgImage(url: string) {
    this.clear();
    const img = new Image();
    img.src = utils.ossSuffix(url, 1024);
    img.crossOrigin = 'anonymous';
    const imgInstance = await new Promise<FabricImage>((resolve, reject) => {
      img.onload = () => {
        const maxSide = Math.max(img.width, img.height);
        const fabricImage = new FabricImage(img, {
          originX: 'center',
          originY: 'center',
          left: 100,
          top: 100,
          width: img.width,
          height: img.height,
          scaleX: 200 / maxSide,
          scaleY: 200 / maxSide,
          angle: 0,
        });
        resolve(fabricImage);
      }
    });
    imgInstance.set({
      containsPoint(point: any, lines: any, absolute: any, calculate: any) {
        // 拾取计算
        return true;
      },
      controls: {
        ...imgInstance.controls,
        tl: removeContorls
      }
    });
    this.fabricCanvas.add(imgInstance);
    this.fabricCanvas.setActiveObject(imgInstance);
    this.fabricCanvas.renderAll();
  }

  //填充
  fill() {
    const canvasWidth = this.fabricCanvas.getWidth();
    const canvasHeight = this.fabricCanvas.getHeight();
    const objects = this.fabricCanvas.getActiveObjects();
    objects.forEach((obj) => {
      const { width, height } = obj;
      const minSide = Math.min(width!, height!);
      obj.set({
        scaleX: canvasWidth / minSide,
        scaleY: canvasHeight / minSide,
        left: canvasWidth / 2,
        top: canvasHeight / 2,
        angle: 0,
      });
    });
    this.fabricCanvas.requestRenderAll();
  }
  //适应
  fit() {
    const canvasWidth = this.fabricCanvas.getWidth();
    const canvasHeight = this.fabricCanvas.getHeight();
    const objects = this.fabricCanvas.getActiveObjects();
    objects.forEach((obj) => {
      const { width, height } = obj;
      const maxSide = Math.max(width!, height!);
      obj.set({
        scaleX: canvasWidth / maxSide,
        scaleY: canvasHeight / maxSide,
        left: canvasWidth / 2,
        top: canvasHeight / 2,
        angle: 0,
      });
    });
    this.fabricCanvas.requestRenderAll();
  }
  //拉伸
  stretch() {
    const canvasWidth = this.fabricCanvas.getWidth();
    const canvasHeight = this.fabricCanvas.getHeight();
    const objects = this.fabricCanvas.getActiveObjects();
    objects.forEach((obj) => {
      const { width, height } = obj;
      obj.set({
        scaleX: canvasWidth / width!,
        scaleY: canvasHeight / height!,
        left: canvasWidth / 2,
        top: canvasHeight / 2,
        angle: 0,
      });
    });
    this.fabricCanvas.requestRenderAll();
  }

  // 简易的历史记录栈
  historyEnable = true;
  stackPointer = -1; // 数据指针
  undoStack: Array<{ version: string; objects: Object[]; }> = [];

  // 记录历史
  recordHistory = () => {
    if (this.historyEnable) {
      this.undoStack = this.undoStack.slice(0, this.stackPointer + 1); // 限制历史记录栈的大小为10
      this.undoStack.push(this.fabricCanvas.toJSON());
      this.stackPointer = this.undoStack.length - 1; // 数据指针指向最后一个数据
    }
  }

  // 撤销操作
  async undo() {
    if (this.stackPointer > 0) {
      this.stackPointer--;
      this.historyEnable = false;
      const state = this.undoStack[this.stackPointer] as never;
      // 恢复到上一个状态
      await this.loadData(state);
      this.historyEnable = true;
    }
  }

  // 重做操作
  async redo() {
    if (this.stackPointer < this.undoStack.length - 1) {
      this.historyEnable = false;
      this.stackPointer++;
      const state = this.undoStack[this.stackPointer] as never;
      // 恢复到上一个状态
      await this.loadData(state);
      this.historyEnable = true;
    }
  }

  //下载当前 fabriccanvas 上的图片
  download() {
    if (this.perCanvas) {
      const dataURL = this.perCanvas.toDataURL('image/png');
      const a = document.createElement('a');
      a.href = dataURL;
      a.download = 'download.png';
      a.click();
    }
  }

  //监听当前选中的效果图和背景数据
  dispose = autorun(() => {
    const { currentIndex, mockupDatas } = addBgModalStore;
    const mockupData = mockupDatas[currentIndex];
    if (mockupData) {
      this.loadData(mockupData);
    }
  }, { delay: 100 });
}

const addBgModalRender = new AddBgModalRender();

export default addBgModalRender;